package mark.wxming.twotigerlock.utils;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @Description
 * redis config
 * db[0-16]<br/>
 * db:0 session<br/>
 * db:1 payRedisLock<br/>
 * db:2 appRedisLock<br/>
 * @Author douxy
 * @Date 2015年10月10日 下午6:12:00 
 */
public class Redis {

    private static Logger Log = Logger.getLogger(Redis.class);
    private static final String host = ConfigUtil.getInstance().getString("redis.host");
    private static final String port = ConfigUtil.getInstance().getString("redis.port");
    private static final String password = ConfigUtil.getInstance().getString("redis.password");
    private static final String maxTotal = ConfigUtil.getInstance().getString("redis.maxTotal");
    private static final String maxIdle = ConfigUtil.getInstance().getString("redis.maxIdle");
    private static final String waitMillis = ConfigUtil.getInstance().getString("redis.waitMillis");
    private static final String enable = ConfigUtil.getInstance().getString("redis.enable");
    private static JedisPool jedisPool = null;

    /**
     * 初始化可用池
     */
    static {
        if ("true".equalsIgnoreCase(enable)) {
            init(1);
        }
    }

    /**
     * 初始化池
     * 
     * @param database
     * @return
     * lockPool is null when redis is unable!
     */
    private static void init(int database) {
        JedisPoolConfig config = new JedisPoolConfig();
        if (!StringUtils.isBlank(maxTotal)) {
            config.setMaxTotal(Integer.parseInt(maxTotal));
        }
        if (!StringUtils.isBlank(maxIdle)) {
            config.setMaxIdle(Integer.parseInt(maxIdle));
        }
        if (!StringUtils.isBlank(waitMillis)) {
            config.setMaxWaitMillis(Integer.parseInt(waitMillis));
        }
        config.setTestOnBorrow(true);
        Log.info("Redis url:" + host + ":" + port);
        jedisPool = new JedisPool(config, host, Integer.parseInt(port), 5000,
            StringUtils.isBlank(password) ? null : password, database);
    }

    /**
     * 获取连接
     * @param database
     * @return
     */
    public static Jedis getResource(int database) {
        return getResource(database, 1);
    }

    /**
     * 获取连接 
     * <br/>
     * 多次尝试防止网络抖动
     * @param database
     * @param trytimes >=1
     * @return
     */
    public static Jedis getResource(int database, int trytimes) {
        if (jedisPool == null) {
            throw new RuntimeException("Redis pool is null,please check.");
        }
        int c = 1;
        Jedis obj = null;
        do {
            c++;
            try {
                obj = jedisPool.getResource();
                obj.select(database);
            } catch (Exception e) {
                Log.error("redis get resource error(" + (c - 1) + ") : " + e.getMessage()
                          + " try again !");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e1) {
                }
            }
        } while (obj == null && c <= trytimes);
        return obj;
    }
}
